using System;
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.CDS;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.FormsManagement;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.ScriptEngine;
using PHSRAG.Utility;
using PageHeader = PHSRAG.Insight21.InsightWebControls.Header;
using ScriptReference=PHSRAG.Insight21.ScriptEngine.ScriptReference;

namespace PHSRAG.Insight21.Humans
{
    /// <summary>
    /// Summary description for AnswerQuestionnairePage.
    /// </summary>
    public partial class AnswerQuestionnairePage : BasePage
    {
        #region Instance Vars.

        private ICachePolicy applicationCachePolicy;
        private ICachePolicy cachePolicy;
        private Hashtable pageCache;
        private ICachePolicy pageCachePolicy;
        private Protocol protocol;
        private int protocolId;
        private ProtocolProcess protocolProcess;
        private int protocolProcessId;
        private int protocolVersionId;
        private QuestionnaireAnswer questAnswer;
        private int questionnaireAnswerId;
        private int questionnaireVersionId;
        private bool removeQAOnCancel;
        //This flag is used to decide whether or not the headers should be displayed
        //If the page is to be displayed as a popup, then the header section is made invisible
        private bool showAsPopUp;
        private int userAccessLevel;

        #endregion

        #region Constants

        private const string AnnunciatorTitle = "The following error(s) occurred...";
        private const string PageCacheKey = "answerQuestionnairePage__C9AD7E48-EF5C-4267-871C-A941705DEB8C";
        private const string ProtocolAccessLevelKey = "ProtocolAccessLevel_8F501635-D683-4bc8-891F-DDD7EA8F23FA";
        private const string ProtocolIdKey = "ProtocolId_4E7DDF5C-6EEA-483b-895E-2ABA7B805EE4";
        private const string ProtocolProcessIdKey = "PPId_842BB447-BD65-477c-81CD-5587922FCC17";
        private const string ProtocolVersionIdKey = "PVId_120C8DF6-BBA3-493a-B525-6B8561B1D5A5";
        private const string QuestionnaireAnswerIdKey = "QAId_F1136FBD-76C7-484c-87CF-3DF56D4D89BA";
        private const string QuestionnaireVersionIdKey = "QVId_1CAF1199-98F3-4f1a-98A5-97D54C5FDEE5";

        #endregion

        #region Properties

        /// <summary>
        /// Gets the protocol for which staffing is being reviewed or modified.  If it's not already
        /// in the cache, it loads it up based on the protocolId passed to the page, and caches the object
        /// </summary>
        private Protocol Protocol
        {
            get
            {
                string cacheKey = Protocol.ProtocolKey;
                protocol = cachePolicy.GetCachedObject(cacheKey) as Protocol;

                if ((protocol == null) || (protocolId != protocol.Id))
                {
                    protocol = new Protocol(cachePolicy);
                    protocol.Load(DataAccess.GetConnectionString(), protocolId);
                    cachePolicy.Cache(cacheKey, protocol);
                }
                return protocol;
            }
        }

        /// <summary>
        /// Gets the protocol process for which staffing is being reviewed or modified.  If it's not already
        /// in the cache, it loads it up based on the protocolProcessId passed to the page, and caches the 
        /// object
        /// </summary>
        private ProtocolProcess ProtocolProcess
        {
            get
            {
                protocolProcess = cachePolicy.GetCachedObject(ProtocolProcess.ProtocolProcessKey)
                    as ProtocolProcess;

                if ((protocolProcess == null) || (protocolProcessId != protocolProcess.Id))
                {
                    if (protocolProcessId > 0)
                    {
                        protocolProcess = ProtocolProcess.GetProtocolProcess(
                            DataAccess.GetConnectionString(), protocolProcessId, cachePolicy, null);
                        cachePolicy.Cache(ProtocolProcess.ProtocolProcessKey, protocolProcess);
                    }
                    else
                    {
                        protocolProcess = null;
                    }
                }
                return protocolProcess;
            }
        }

        #endregion

        protected void OnPageLoad(object sender, EventArgs e)
        {
            try
            {
                pageCache = pageCachePolicy.GetCachedObject(PageCacheKey) as Hashtable ?? new Hashtable();

                breadCrumb.Add(
                    "Answer Questionnaire",
                    Settings.GetKeyValue("SubModuleNavigation.Humans.AnswerQuestionnairePageURL", ""),
                    Settings.GetKeyValue("BreadCrumb.DetailPageLevel", 2));

                if (!IsPostBack)
                {
                    cancel.Attributes.Add("onKeyPress", "Save()");
                    // get the stuff out of the cache.
                    Hashtable incomingPageHash =
                        cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                    if (incomingPageHash != null)
                    {
                        protocolId = Convert.ToInt32(incomingPageHash[Keys.ProtocolIdKey]);
                        pageCache[ProtocolIdKey] = protocolId;
                        protocol = new Protocol(cachePolicy);
                        protocol.Load(DataAccess.GetConnectionString(), protocolId);
                        protocol.Cache();
                        protocolProcessId = Convert.ToInt32(incomingPageHash[Keys.ProtocolProcessIdKey]);
                        pageCache[ProtocolProcessIdKey] = protocolProcessId;
                        protocolProcess = ProtocolProcess.GetProtocolProcess(DataAccess.GetConnectionString(), protocolProcessId, cachePolicy, null);
                        protocolProcess.Cache();

                        userAccessLevel = Convert.ToInt32(incomingPageHash[Keys.ProtocolAccessKey]);
                        pageCache[ProtocolAccessLevelKey] = userAccessLevel;

                        if (incomingPageHash.ContainsKey(Keys.ShowAsPopUp))
                        {
                            showAsPopUp = Convert.ToBoolean(incomingPageHash[Keys.ShowAsPopUp]);
                        }
                        pageCache[Keys.ShowAsPopUp] = showAsPopUp;


                        protocolVersionId = Convert.ToInt32(incomingPageHash[Keys.ProtocolVersionIdKey]);
                        pageCache[ProtocolVersionIdKey] = protocolVersionId;
                        questionnaireVersionId = Convert.ToInt32(incomingPageHash[Keys.QuestionnaireVersionIdKey]);
                        pageCache[QuestionnaireVersionIdKey] = questionnaireVersionId;
                        questionnaireAnswerId = Convert.ToInt32(incomingPageHash[Keys.QuesionnaireAnswerIdKey]);
                        pageCache[QuestionnaireAnswerIdKey] = questionnaireAnswerId;
                        if (incomingPageHash.ContainsKey(Keys.RemoveQAOnCancel))
                        {
                            removeQAOnCancel = Convert.ToBoolean(incomingPageHash[Keys.RemoveQAOnCancel]);
                            pageCache[Keys.RemoveQAOnCancel] = removeQAOnCancel;
                        }

                        // get the QuestionnaireVersion and Answer Ids.
                        QuestionnaireVersion questVersion = new QuestionnaireVersion(cachePolicy);
                        questVersion.Load(DataAccess.GetConnectionString(), questionnaireVersionId);
                        if (questionnaireAnswerId == 0)
                        {
                            questAnswer = new QuestionnaireAnswer(cachePolicy);
                            questAnswer = (QuestionnaireAnswer) cachePolicy.GetCachedObject(questAnswer.CacheKey());
                            if (questAnswer.Id != 0)
                            {
                                throw new Exception("Invalid context.");
                            }
                        }
                        else
                        {
                            questAnswer = new QuestionnaireAnswer(cachePolicy);
                            questAnswer.Load(DataAccess.GetConnectionString(), questionnaireAnswerId);
                        }

                        // set these on the Control
                        if (questVersion.Questionnaire.AllowMultiple)
                        {
                            questionnaireViewer.QuestionnaireAnswerName = questAnswer.Name;
                        }
                        questionnaireViewer.LoadQuestionnaire(questVersion, questAnswer);
                        pageCachePolicy.UnCache(Keys.IncomingDataKey);
                        pageCachePolicy.Cache(PageCacheKey, pageCache);

                        //name of the questionnaire
                        questionaireTitle.Text = questVersion.Questionnaire.Name;
                    }
                    else
                    {
                        protocolId = (int) pageCache[ProtocolIdKey];
                        questionnaireAnswerId = (int) pageCache[QuestionnaireAnswerIdKey];
                        protocolProcessId = (int) pageCache[ProtocolProcessIdKey];
                        protocolVersionId = (int) pageCache[ProtocolVersionIdKey];
                        questionnaireVersionId = (int) pageCache[QuestionnaireVersionIdKey];
                        userAccessLevel = (int) pageCache[ProtocolAccessLevelKey];
                        showAsPopUp = (bool) pageCache[Keys.ShowAsPopUp];

                        if (pageCache.ContainsKey(Keys.RemoveQAOnCancel))
                        {
                            removeQAOnCancel = Convert.ToBoolean(pageCache[Keys.RemoveQAOnCancel]);
                            pageCache[Keys.RemoveQAOnCancel] = removeQAOnCancel;
                        }
                        // get the QuestionnaireVersion and Answer Ids.
                        QuestionnaireVersion questVersion = new QuestionnaireVersion(cachePolicy);
                        questVersion.Load(DataAccess.GetConnectionString(), questionnaireVersionId);
                        if (questionnaireAnswerId == 0)
                        {
                            questAnswer = new QuestionnaireAnswer(cachePolicy);
                            questAnswer = (QuestionnaireAnswer) cachePolicy.GetCachedObject(questAnswer.CacheKey());
                            if (questAnswer.Id != 0)
                            {
                                throw new Exception("Invalid context.");
                            }
                        }
                        else
                        {
                            questAnswer = new QuestionnaireAnswer(cachePolicy);
                            questAnswer.Load(DataAccess.GetConnectionString(), questionnaireAnswerId);
                        }
                    }
                }
                else
                {
                    protocolId = (int) pageCache[ProtocolIdKey];
                    questionnaireAnswerId = (int) pageCache[QuestionnaireAnswerIdKey];
                    protocolProcessId = (int) pageCache[ProtocolProcessIdKey];
                    protocolVersionId = (int) pageCache[ProtocolVersionIdKey];
                    questionnaireVersionId = (int) pageCache[QuestionnaireVersionIdKey];
                    userAccessLevel = (int) pageCache[ProtocolAccessLevelKey];
                    showAsPopUp = (bool) pageCache[Keys.ShowAsPopUp];
                    if (pageCache.ContainsKey(Keys.RemoveQAOnCancel))
                    {
                        removeQAOnCancel = (bool) pageCache[Keys.RemoveQAOnCancel];
                    }


                    // get the QuestionnaireVersion and Answer Ids.
                    QuestionnaireVersion questVersion = new QuestionnaireVersion(cachePolicy);
                    questVersion.Load(DataAccess.GetConnectionString(), questionnaireVersionId);
                    if (questionnaireAnswerId == 0)
                    {
                        questAnswer = new QuestionnaireAnswer(cachePolicy);
                        questAnswer = (QuestionnaireAnswer) cachePolicy.GetCachedObject(questAnswer.CacheKey());
                        if (questAnswer.Id != 0)
                        {
                            throw new Exception("Invalid context.");
                        }
                    }
                    else
                    {
                        questAnswer = new QuestionnaireAnswer(cachePolicy);
                        questAnswer.Load(DataAccess.GetConnectionString(), questionnaireAnswerId);
                    }
                }


                //if page is being shown as popup, then hide the header section
                headerSection.Visible = !showAsPopUp;
            }
            catch (Exception ex)
            {
                annunciator.Message = ex.Message;
                saveButton.Enabled = false;
            }
            finally
            {
                protocolDetailHeader.ProtocolID = protocolId;

                if (header.ModuleName.ToLower() == "humans")
                {
                    //Set the humansubmodule Navigation links
                    humansSubModuleNavigation.Visible = true;
                    animalsSubModuleNavigation.Visible = false;
                    humansSubModuleNavigation.ProtocolProcess = ProtocolProcess;
                    humansSubModuleNavigation.Protocol = Protocol;
                    humansSubModuleNavigation.SelectedLink = "Forms";
                }
                else
                {
                    humansSubModuleNavigation.Visible = false;
                    animalsSubModuleNavigation.Visible = true;
                    animalsSubModuleNavigation.ProtocolProcess = ProtocolProcess;
                    animalsSubModuleNavigation.Protocol = Protocol;
                    animalsSubModuleNavigation.SelectedLink = "Forms";
                }
            }
        }

        /// <summary>
        /// OnClick is fired when the Save button is clicked.
        /// </summary>
        /// <param name="sender">The control which raised the event.</param>
        /// <param name="e">Arguments assocoiated with the event</param>
        private void OnClick(object sender, ImageClickEventArgs e)
        {
            try
            {
                if (questAnswer != null)
                {
                    UserContext loggedInUserContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
                    questAnswer.LastModifiedByAdmPersonId = loggedInUserContext.PersonId;
                }
                if (!questionnaireViewer.VerifyTextboxAnswers())
                {
                    return;
                }
                // grab the list of questions from the Forms control, and save them as appropriate
                if (!questionnaireViewer.SaveQuestionnaire(questAnswer))
                {
                    return;
                }

                //If the protocol version is a clone of an existing version, then add it to the versions collection on the process.
                ProtocolVersion currentProtocolVersion = new ProtocolVersion(cachePolicy);
                currentProtocolVersion = (ProtocolVersion) cachePolicy.GetCachedObject(currentProtocolVersion.CacheKey());

                if (protocolVersionId == 0)
                {
                    if (currentProtocolVersion.Id != 0)
                    {
                        throw new Exception("Invalid context");
                    }

                    if (currentProtocolVersion.QuestionnaireAnswers == null)
                    {
                        currentProtocolVersion.QuestionnaireAnswers = new ArrayList();
                    }
                    // find & replace the original one.
                    int count = currentProtocolVersion.QuestionnaireAnswers.Count;

                    for (int i = 0; i < count; ++i)
                    {
                        QuestionnaireAnswer currAnswer = (QuestionnaireAnswer) currentProtocolVersion.QuestionnaireAnswers[i];

                        if (currAnswer.Name == questAnswer.Name)
                        {
                            currentProtocolVersion.QuestionnaireAnswers.RemoveAt(i);
                            break;
                        }
                    }
                    currentProtocolVersion.QuestionnaireAnswers.Add(questAnswer);

                    ProtocolProcess.ProtocolVersions.Add(currentProtocolVersion);
                }
                else
                {
                    questAnswer.Save(DataAccess.GetConnectionString());
                    // Null this collection so it will be reloaded from the db.  Previously,
                    // the questionnaireanswer representing this questionnaire didn't have the
                    // answers populated.
                    currentProtocolVersion.QuestionnaireAnswers = null;
                }

                ProtocolProcess.VerifyRequiredAttachments(questAnswer, ((RefCodes) applicationCachePolicy.GetCachedObject(RefCodes.CacheKey)), currentProtocolVersion);
                ProtocolProcess.LastModifiedDate = DateTime.Now;
                ProtocolProcess.Save(DataAccess.GetConnectionString());

                if (protocolVersionId == 0)
                {
                    protocolVersionId = currentProtocolVersion.Id;
                }

                // add to the outgoing page cache the IDs needed...
                Hashtable outgoingData = new Hashtable();
                outgoingData.Add(Keys.ProtocolIdKey, protocolId);
                outgoingData.Add(Keys.ProtocolProcessIdKey, protocolProcessId);
                outgoingData.Add(Keys.ProtocolVersionIdKey, protocolVersionId);
                outgoingData.Add(Keys.ProtocolAccessKey, userAccessLevel);
                pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);

                // Run the requirement script for the appropriate QuestionnaireVersion here.
                QuestionnaireVersion version = questAnswer.QuestionnaireVersion;

                Script requirementScript =
                    (Script) version.Scripts[FormsManagement.Constants.ScriptType.Requirement];

                if (requirementScript != null)
                {
                    using (ScriptEngineHost scriptHost =
                        new ScriptEngineHost(
                            string.Format("{0}{1}", version.Id,
                                ScriptEngine.Constants.RootMoniker.RequirementScriptMoniker),
                            ScriptEngine.Constants.RootNamespaces.RequirementScript,
                            true))
                    {
                        ArrayList refs = ScriptReference.GetAllScriptReferences(
                            DataAccess.GetConnectionString());

                        for (int i = 0; i < refs.Count; ++i)
                        {
                            ScriptReference reference = (ScriptReference) refs[i];
                            scriptHost.AddDLLReference(reference.Path);
                        }

                        protocol = cachePolicy.GetCachedObject(Protocol.ProtocolKey) as Protocol;
                        if (protocol == null)
                        {
                            protocol.Load(DataAccess.GetConnectionString(), protocolId);
                        }

                        // add this protocol as an intrinsic.
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.Protocol, protocol);

                        // add the connection string
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ConnectionString,
                            DataAccess.GetConnectionString());

                        // add the QuestionnaireAnswer
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.QuestionnaireAnswer,
                            questAnswer);
                        //process
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ProtocolProcss, ProtocolProcess);
                        // add the versionhttp://localhost/Insight/Humans/ActiveProtocols.aspx
                        ProtocolVersion protocolVersion = new ProtocolVersion(cachePolicy);
                        protocolVersion.Load(DataAccess.ConnectionString, protocolVersionId);
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ProtocolVersion, protocolVersion);

                        // add the caching policy
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.CachePolicy, cachePolicy);

                        // compile and run the script.
                        if (scriptHost.Compile(requirementScript))
                        {
                            scriptHost.RunScript(requirementScript,
                                ScriptEngine.Constants.AssemblyType.RequirementScript,
                                ScriptEngine.Constants.MethodsToRun.Main);
                        }
                    }
                }

                protocol.UnCache();
                protocol.Cache();

                // cache some things
                outgoingData = new Hashtable();
                outgoingData.Add(Keys.ProtocolIdKey, protocolId);
                outgoingData.Add(Keys.ProtocolProcessIdKey, protocolProcessId);
                outgoingData.Add(Keys.ProtocolAccessKey, userAccessLevel);
                outgoingData.Add(Keys.ShowAsPopUp, showAsPopUp);
                pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);

                // now that it's saved, redirect the user to the ProtocolProcessOverview page.
                Page.Response.Redirect(
                    Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolProcessOverviewURL", ""), false);
            }
            catch (Exception ex)
            {
                annunciator.Message = ex.Message;
                saveButton.Enabled = false;
            }
        }

        /// <summary>
        /// migrates back to previous page without saving the changes.
        /// </summary>
        /// <param name="sender">The control(back button) which raised the event.</param>
        /// <param name="e">Arguments assocoiated with the event</param>
        private void OnCancel(object sender, ImageClickEventArgs e)
        {
            try
            {
                if (removeQAOnCancel)
                {
                    ProtocolVersion pV = new ProtocolVersion(cachePolicy);
                    pV.Load(DataAccess.ConnectionString, protocolVersionId);
                    pV.DeleteQuestionnaireAnswer(questAnswer.Id);
                }
                CacheOutgoingData();
                // redirect the user to the ProtocolProcessOverview page.
                Page.Response.Redirect(
                    Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolProcessOverviewURL", ""), false);
            }
            catch (Exception ex)
            {
                annunciator.Message = ex.Message;
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link before the breadCrumb performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnBreadCrumbNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                humansSubModuleNavigation.Reset();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link before the header or the breadCrumb performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                humansSubModuleNavigation.Reset();
                humansSubNavigation.Reset();
                OnNavigate();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Constructs and caches a hashtable of data for use by the page to which nagivation leads
        /// </summary>
        private void OnNavigate()
        {
            try
            {
                CacheOutgoingData();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Displays an error message on the screen to the user with the exception, and all
        /// inner exception messages.
        /// </summary>
        /// <param name="ex">The exception to report on</param>
        private void DisplayExceptionReport(Exception ex)
        {
            annunciator.Title = AnnunciatorTitle;
            annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
        }

        /// <summary>
        /// Stores the data relevant to the destination page in a hashtable and caches it under the 
        /// IncomingData key
        /// </summary>
        private void CacheOutgoingData()
        {
            Hashtable outgoingData = new Hashtable();
            outgoingData.Add(Keys.ProtocolIdKey, protocolId);
            outgoingData.Add(Keys.ProtocolProcessIdKey, protocolProcessId);
            outgoingData.Add(Keys.ProtocolAccessKey, userAccessLevel);
            outgoingData.Add(Keys.ShowAsPopUp, showAsPopUp);
            pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
        }

        #region Web Form Designer generated code

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);

            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
            applicationCachePolicy = (Policy.ICachePolicy) Application[Policy.Names.ApplicationCachePolicyKey];
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.header.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnNavigate);
            this.humansSubModuleNavigation.Navigate += new PHSRAG.Insight21.InsightWebControls.HumansSubModuleNavigation.NavigateEventHandler(this.OnNavigate);
            this.animalsSubModuleNavigation.Navigate += new CommandEventHandler(this.OnNavigate);
            this.breadCrumb.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnBreadCrumbNavigate);
            this.cancel.Click += new ImageClickEventHandler(OnCancel);
            this.saveButton.Click += new ImageClickEventHandler(OnClick);
            this.Load += new System.EventHandler(this.OnPageLoad);
        }

        #endregion
    }
}